package com.hmall.item.mq;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

@Component
public class SpringRabbitListener {

    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String message) {
        System.out.println("接受到消息：" + message);
    }

    @RabbitListener(queues = "object.queue")
    public void listenObjectQueue(Object message) {
        System.out.println("接受到消息：" + message);
    }

    // 一个队列中的一条消息只能被一个消费者处理，也就是消息被消费了
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String message) throws InterruptedException {
        System.out.println("消费者1收到消息：" + message);
        Thread.sleep(25);
    }

    /*
    两个消费者监听同一个队列，则队列的消息将被这些消费者平均轮流处理，
    这里用Thread.sleep阻塞模拟不同消费者处理速度不同，发现默认情况下仍然满足平均分配，
    但是这样就存在性能浪费的问题，对此可以在配置文件中设置prefetch参数为1，
    这样消费者处理完一条消息后才能获取下一条消息，那么速度快的消费者最终将处理更多消息
     */
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String message) throws InterruptedException {
        System.out.println("消费者2收到消息：" + message);
        Thread.sleep(200);
    }

    /*
    从fanout（广播模式）交换机发送的消息同时会发给绑定的多个队列，
    消费者从各自监听的队列获取到相同的消息，完成各自的任务
     */
    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String message) {
        System.out.println("fanout.queue1收到消息：" + message);
    }
    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String message) {
        System.out.println("fanout.queue2收到消息：" + message);
    }

    /*
    从direct（路由模式）交换机发送的消息同时会发给Routing Key绑定的多个队列，
    消费者从各自监听的队列获取到相同的消息，完成各自的任务
     */
    @RabbitListener(queues = "direct.queue1")
    public void listenDirectQueue1(String message) {
        System.out.println("direct.queue1收到消息：" + message);
    }
    @RabbitListener(queues = "direct.queue2")
    public void listenDirectQueue2(String message) {
        System.out.println("direct.queue2收到消息：" + message);
    }

    // 注解方式声明交换机、队列和routingKey，不存在的会创建
    /*
    x-queue-mode设定lazy采用RabbitMQ的Lazy Queue模式，在控制台创建队列时可以点击下方Lazy Mode按钮添加该参数
    这个模式是从3.6版本开始提供的，而从3.12版本开始，队列均默认采用该模式
    这种模式是不写内存而直接写入磁盘，但是又优化了写入磁盘的逻辑使得速度尽可能快，解决了消息堆积到内存需要写入磁盘时队列被阻塞导致并发量下降的问题
    并且在读取消息时也做了优化，mq统计消费者处理消息的速度，当mq从磁盘读取数据的速度赶不上消费者的速度时会预先将一定数量的消息读取到内存
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "lhr.directQueue1", durable = "true",
                    arguments = @Argument(name = "x-queue-mode", value = "lazy")),
            exchange = @Exchange(value = "lhr.direct", type = ExchangeTypes.DIRECT),
            key = {"red", "blue"}
    ))
    public void listenLhrDirectQueue1(String message) {
        System.out.println("lhr.directQueue1收到消息：" + message);
    }
}
